/*************************************************************************
 *          HONGLING CAPITAL CONFIDENTIAL AND PROPRIETARY
 *
 *          COPYRIGHT (C) HONGLING CAPITAL CORPORATION 2012
 *    ALL RIGHTS RESERVED BY HONGLING CAPITAL CORPORATION. THIS PROGRAM
 * MUST BE USED SOLELY FOR THE PURPOSE FOR WHICH IT WAS FURNISHED BY
 * HONGLING CAPITAL CORPORATION. NO PART OF THIS PROGRAM MAY BE REPRODUCED
 * OR DISCLOSED TO OTHERS, IN ANY FORM, WITHOUT THE PRIOR WRITTEN
 * PERMISSION OF HONGLING CAPITAL CORPORATION. USE OF COPYRIGHT NOTICE
 * DOES NOT EVIDENCE PUBLICATION OF THE PROGRAM.
 *          HONGLING CAPITAL CONFIDENTIAL AND PROPRIETARY
 *************************************************************************/

package com.itlong.cloud.utils.node;

import com.alibaba.fastjson.JSON;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.core.JsonFactory;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.JavaType;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;import org.slf4j.LoggerFactory;

import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.io.StringWriter;
import java.util.HashMap;
import java.util.Map;

/**
 * <desc>
 *     JSON序列化和反序列化辅助方法集合。
 * </desc>
 * @createDate 2017/08/29
 */
public class JsonUtil {
    private static final Logger LOG = LoggerFactory.getLogger(JsonUtil.class);

    private JsonUtil() {
        super();
    }

    private static final ObjectMapper mapper = new ObjectMapper();
    static{
        //        忽略json中多余的字段防止转化object类型时报错
        mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES,false);
        mapper.configure(JsonParser.Feature.ALLOW_UNQUOTED_FIELD_NAMES, true);
        mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
    }

    /**
     * <desc>
     *      从request中获取参数
     * </desc>
     *
     * @param request
     * @return
     * @author Jiaqi.X
     * @createDate 2018/04/04
     */
    public static <T> T getHttpParams(HttpServletRequest request,Class<T> clazz) throws IOException {
         return request.getAttribute("params") != null ? JsonUtil.toObject(request.getAttribute("params").toString(),clazz) : null ;
    }

    /**
     * {@link Map Map}-><a href="http://www.json.org/">JSON</a>格式的字符串。
     *
     * @param target {@link Map Map}实例。
     * @param <T> 泛型声明。
     * @return JSON格式字符串。
     * @throws IOException {@link JsonFactory#createGenerator(java.io.Writer)}可能抛出的例外。
     * @see JsonFactory#createGenerator(java.io.Writer)
     * @see ObjectMapper#writeValue(com.fasterxml.jackson.core.JsonGenerator, Object)
     */
    public static <T> String toJSON(Object target) throws IOException {
        StringWriter writer = new StringWriter();
        mapper.writeValue(new JsonFactory().createGenerator(writer), target);
        return writer.toString();
    }

    /**
     * <a href="http://www.json.org/">JSON</a>格式的字符串->{@code <T>}对象。
     *
     * @param JSON JSON格式字符串。
     * @param clazz 要转换对象的类类型。
     * @param <T> 泛型声明。
     * @return 指定类类型的对象实例。
     * @throws IOException {@link ObjectMapper#readValue(String, Class)}可能抛出的例外。
     */
    public static <T> T toObject(String JSON, Class<T> clazz) throws IOException {
        if(StringUtils.isBlank(JSON)){
            return null;
        }else {
            return mapper.readValue(JSON, clazz);
        }
    }

    /**
     * <desc>
     *      转换List<Object> json格式的数据
     * </desc>
     *
     * @param JSON  json字符串
     * @param listClass List的对象类类型
     * @param objectClass Object的对象类类型
     * @param <T> 泛型声明
     * @return
     * @throws IOException
     * @author Jiaqi.X
     * @createDate 2017/11/10
     */
    public static <T> T toListObject(String JSON,Class<?> listClass,Class<T> objectClass) throws IOException {
        JavaType javaType=mapper.getTypeFactory().constructParametricType(listClass, objectClass);
        return mapper.readValue(JSON, javaType);
    }

    /**
     * 将json array反序列化为对象
     *
     * @param json
     * @param jsonTypeReference
     * @return
     */
    public static <T> T decode(String json, TypeReference<T> jsonTypeReference) throws IOException {
        try {
            return (T) mapper.readValue(json, jsonTypeReference);
        } catch (IOException e) {
            LOG.error("decode(String, JsonTypeReference<T>)", e);
            throw e;
        }
    }

    public static Map<String,Object> JsonToMap(String json) {
        Map<String,Object> map = new HashMap<>();
        if (json != null) {
            map = (Map) JSON.parse(json);
        }
        return map;
    }
}
